#include "helper.h"
#include "exec.h"
#include <stdio.h>
#include <stdlib.h>

// note: pc not synchronized yet
#define INST insn

target_size_t
helper_ldr (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t ret;
    //puts ("helper_ldr\n");
    ret = read_memory (ms, (REG (BaseR) + imm6) & 0xFFFF, &(REG (DR)));
    SET_FLAGS ();
    return ret;
}

target_size_t
helper_ld (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    //puts ("helper_ld\n");
    target_size_t ret;
    ret = read_memory (ms, (pc + imm9) & 0xFFFF, &(REG (DR)));
    SET_FLAGS ();
    return ret;
}

target_size_t
helper_ldi (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t tmp, ret;
    //puts ("helper_ldi\n");
    read_memory (ms, (pc + imm9) & 0xFFFF, &tmp);
    ret = read_memory (ms, tmp, &(REG (DR)));
    SET_FLAGS ();
    return ret;
}

target_size_t
helper_st (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t ret;
    //puts ("helper_st\n");
    ret = write_memory (ms, (pc + imm9) & 0xFFFF, REG (SR));
    return ret;
}

target_size_t
helper_sti (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t tmp, ret;
    //puts ("helper_sti\n");
    read_memory (ms, (pc + imm9) & 0xFFFF, &tmp);
    ret = write_memory (ms, tmp, REG (SR));
    return ret;
}

target_size_t
helper_str (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t ret;
    //puts ("helper_str\n");
    ret = write_memory (ms, (REG (BaseR) + imm6) & 0xFFFF, REG (SR));
    return ret;
}

target_size_t
helper_trap (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    target_size_t ret;
    //puts ("helper_trap\n");
    REG (R_R7) = pc;
    ret = read_memory (ms, vec8, &(REG (R_PC)));
    return ret;
}

target_size_t
helper_add (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    //puts ("helper_trap\n");
    REG (DR) = (REG (SR1) + REG (SR2)) & 0xFFFF;
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_addi (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    REG (DR) = (REG (SR1) + imm5) & 0xFFFF;
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_and (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    //puts ("helper_trap\n");
    REG (DR) = REG (SR1) & REG (SR2);
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_andi (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    //puts ("helper_trap\n");
    REG (DR) = REG (SR1) & imm5;
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_lea (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    REG (DR) = (REG (R_PC) + imm9) & 0xFFFF;
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_not (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    REG (DR) = (REG (SR1) ^ 0xFFFF);
    SET_FLAGS ();
    return 0;
}

target_size_t
helper_set_cc (target_size_t* registers, MachineStatus *ms, target_size_t pc, target_size_t insn) {
    SET_FLAGS ();
    return 0;
}

char* itoa(size_t num,char* str,int radix)
{
    char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//索引表
    size_t unum;//存放要转换的整数的绝对值,转换的整数可能是负数
    size_t i=0,j,k;//i用来指示设置字符串相应位，转换之后i其实就是字符串的长度；转换后顺序是逆序的，有正负的情况，k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。
 
    //获取要转换的整数的绝对值
    if(radix==10&&num<0)//要转换成十进制数并且是负数
    {
        unum=(unsigned)-num;//将num的绝对值赋给unum
        str[i++]='-';//在字符串最前面设置为'-'号，并且索引加1
    }
    else unum=(size_t)num;//若是num为正，直接赋值给unum
 
    //转换部分，注意转换后是逆序的
    do
    {
        str[i++]=index[unum%(size_t)radix];//取unum的最后一位，并设置为str对应位，指示索引加1
        unum/=radix;//unum去掉最后一位
 
    }while(unum);//直至unum为0退出循环
 
    str[i]='\0';//在字符串最后添加'\0'字符，c语言字符串以'\0'结束。
 
    //将顺序调整过来
    if(str[0]=='-') k=1;//如果是负数，符号不用调整，从符号后面开始调整
    else k=0;//不是负数，全部都要调整
 
    char temp;//临时变量，交换两个值时用到
    for(j=k;j<=(i-1)/2;j++)//头尾一一对称交换，i其实就是字符串的长度，索引最大值比长度少1
    {
        temp=str[j];//头部赋值给临时变量
        str[j]=str[i-1+k-j];//尾部赋值给头部
        str[i-1+k-j]=temp;//将临时变量的值(其实就是之前的头部值)赋给尾部
    }
 
    return str;//返回转换后的字符串
 
}

int
helper_dbg (size_t data) {
    // char buffer [1024];
    // puts (itoa (data,buffer, 16));
    // if (data <= INSN_TRAP)
    //     puts (insn_name[data]);
    // else
    //     puts ("INVAL INSN");
    return 0;
}
